#include "smart-device-gateway.h"

SmartDeviceGateway::SmartDeviceGateway(const string &uartDevice)
    : udpNetThread(nullptr),
      mqttThread(nullptr),
      worker(uartDevice)
{
	udpNetCommunication        = new UdpNetCommunication("192.168.2.109", 8899);
	mqttNetCommunication       = new MQTTNetCommunication("192.168.2.109", 1883);
	communicationHandlerThread = new thread(std::bind(&SmartDeviceGateway::communicationHandlerRun, this));
}

SmartDeviceGateway::~SmartDeviceGateway()
{
	delete udpNetCommunication;
}

void SmartDeviceGateway::start(void)
{
	if(!udpNetThread)
	{
		udpNetThread = new thread(std::bind(&SmartDeviceGateway::udpNetCommunicationRun, this));
	}

	if(!mqttThread)
	{
		mqttThread = new thread(std::bind(&SmartDeviceGateway::mqttCommunicationRun, this));
	}
}

void SmartDeviceGateway::udpNetCommunicationRun(void)
{
	//收到的请求放到队列中去 唤醒从队列中请求处理的线程
	//队列中的数据：请求包+mqtt/udp
	while(1)
	{
		vector<uint8_t> packet;
		bool            ok = udpNetCommunication->recvPacket(packet);
		if(!ok)
		{
			break;
		}
		queueMtx.lock();
		messageQueue.push(CommunicationMessage(packet, udpNetCommunication));
		queueMtx.unlock();
		//唤醒 communicationHandlerRun
		notify();
	}
}

void SmartDeviceGateway::mqttCommunicationRun(void)
{
	while(1)
	{
		vector<uint8_t> packet;
		char            buf[1024] = {0};
		bool            ok        = mqttNetCommunication->recvPacket(packet);
		if(!ok)
		{
			break;
		}
		queueMtx.lock();
		messageQueue.push(CommunicationMessage(packet, mqttNetCommunication));
		queueMtx.unlock();
		//唤醒 communicationHandlerRun
		notify();
	}
}

void SmartDeviceGateway::communicationHandlerRun(void)
{

	while(1)
	{
		queueMtx.lock();
		bool queueEmpty = messageQueue.empty();
		queueMtx.unlock();

		if(queueEmpty)
		{
			//等待唤醒
			wait();
		}

		queueMtx.lock();
		CommunicationMessage message = messageQueue.front();
		messageQueue.pop();
		queueMtx.unlock();

		//对message进行处理
		worker.doWork(message);
	}
}

/**
 * 线程等待
*/
void SmartDeviceGateway::wait(void)
{
	std::unique_lock<std::mutex> lck(mtx);
	cv.wait(lck);
}

/**
 * 线程唤醒
*/
void SmartDeviceGateway::notify(void)
{
	std::unique_lock<std::mutex> lck(mtx);
	cv.notify_all();
}
